package com.springboot.lotterysystem.service.impl;

import cn.hutool.crypto.digest.DigestUtil;
import com.springboot.lotterysystem.common.errorcode.ServiceErrorCodeConstants;
import com.springboot.lotterysystem.common.exception.ServiceException;
import com.springboot.lotterysystem.common.utils.RegexUtil;
import com.springboot.lotterysystem.controller.param.UserRegisterParam;
import com.springboot.lotterysystem.dao.dataobject.Encrypt;
import com.springboot.lotterysystem.dao.dataobject.UserDO;
import com.springboot.lotterysystem.dao.mapper.UserMapper;
import com.springboot.lotterysystem.service.UserService;
import com.springboot.lotterysystem.service.dto.UserRegisterDTO;
import com.springboot.lotterysystem.service.enums.UserIdentityEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

/**
 * Created with IntelliJ IDEA.
 * Description :
 * User: jiume
 * Date: 2025-04-20
 * Time: 14:47
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserRegisterDTO register(UserRegisterParam param) {
        // 1、校验注册参数信息
        checkRegisterInfo(param);
        // 2、对数据进行加密处理
        UserDO userDO = new UserDO();
        userDO.setUserName(param.getName());
        userDO.setEmail(param.getMail());
        userDO.setPhoneNumber(new Encrypt(param.getPhoneNumber()));
        // 可能没有密码，得先去判断
        if (StringUtils.hasText(param.getPassword())) {
            // 还得先对密码先加密处理
            userDO.setPassword(DigestUtil.sha256Hex(param.getPassword()));
        }
        userDO.setIdentity(param.getIdentity());
        // 3、存储到数据库中
        userMapper.insert(userDO);
        // 4、构造返回
        UserRegisterDTO userRegisterDTO = new UserRegisterDTO();
        userRegisterDTO.setUserId(userDO.getId());
        return userRegisterDTO;
    }

    /**
     * 校验注册参数
     * @param param 注册信息
     */
    private void checkRegisterInfo(UserRegisterParam param) {
        if (param == null) {
            throw new ServiceException(ServiceErrorCodeConstants.REGISTER_INFO_IS_EMPTY);
        }
        // 1、校验邮箱格式
        if (!RegexUtil.checkMail(param.getMail())) {
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_ERROR);
        }

        // 2、校验手机格式
        if (!RegexUtil.checkMobile(param.getPhoneNumber())) {
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }

        // 3、校验身份信息
        // 身份信息是String类型，而代码中对应的是枚举类，可以name来获取
        if (UserIdentityEnum.forName(param.getIdentity()) == null) {
            throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
        }

        // 4、校验管理员身份密码必填
        // 首先得判断当前身份信息是否为管理员用户，其次再去判断密码是否为空
        if (param.getIdentity().equalsIgnoreCase(UserIdentityEnum.ADMIN.getIdentity())
                && !StringUtils.hasText(param.getPassword())) {
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_IS_EMPTY);
        }

        // 5、密码校验（长度要满足6-12位）
        // 同样先要判断是否为管理员用户
        if (param.getIdentity().equalsIgnoreCase(UserIdentityEnum.ADMIN.getIdentity())
                && !RegexUtil.checkPassword(param.getPassword())) {
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_ERROR);
        }

        // 6、确保 用户名、手机号、邮箱是否唯一（查询是否已经存在）
        if (checkMailUsed(param.getMail())) {
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_USED);
        }

        if (checkPhoneNumberUsed(param.getPhoneNumber())) {
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_USED);
        }

        // TODO 判断用户名是否被使用（是否已经存在）
    }

    // 判断手机号是否被使用
    private boolean checkPhoneNumberUsed(String phoneNumber) {
        int count = userMapper.countByPhoneNumber(new Encrypt(phoneNumber));
        return count >= 1;
    }

    // 判断邮箱是否被使用过
    private boolean checkMailUsed(String mail) {
        // 去数据库中查询其是否被使用（也就是是否存在该邮箱的信息）
        int count = userMapper.countByMail(mail);
        return count >= 1;
    }
}
